Webframeworkk/ASP.NET Core/Middleware

Dieses Tutorial erklärt das Konzept der Middleware in ASP.NET Core, wie sie funktioniert, wie man sie konfiguriert und wie man eigene Middleware-Komponenten erstellt. Es basiert auf den bereitgestellten Notizen und ergänzendem Expertenwissen.

Was ist Middleware?

Middleware in ASP.NET Core ist eine Software-Pipeline, durch die jede HTTP-Anfrage (Request) und jede Antwort (Response) fließt. Man kann sich diese Pipeline wie eine Reihe von hintereinander geschalteten Rohren oder Ventilen vorstellen.

Jede Middleware-Komponente hat drei Hauptaufgaben:

  1. Untersuchen der eingehenden Anfrage.
  2. Bearbeiten der Anfrage oder der Antwort.
  3. Weiterleiten an die nächste Middleware oder Beenden (Short-Circuit) der Pipeline.

Dies ermöglicht eine saubere Modularisierung von Funktionen wie Authentifizierung, Logging, Fehlerbehandlung und Routing.


Grundlagen: app.Use vs. app.Run

Es gibt zwei grundlegende Methoden, um Middleware zur Pipeline hinzuzufügen:

1. app.Run (Terminale Middleware)

Diese Methode fügt eine terminale Middleware hinzu. Das bedeutet, sie beendet die Pipeline. Es wird kein next-Delegat aufgerufen, und nachfolgende Middleware-Komponenten werden nicht ausgeführt.

Beispiel:

app.Run(async (context) => {
    await context.Response.WriteAsync("Ende der Pipeline");
});

Warnung: Wenn Sie zwei app.Run-Aufrufe hintereinander haben, wird nur der erste ausgeführt!

2. app.Use (Verkettbare Middleware)

Diese Methode dient dazu, Aufgaben zu erledigen und dann (meistens) die nächste Komponente in der Kette aufzurufen.

Beispiel:

app.Use(async (context, next) => {
    // Logik VOR dem nächsten Middleware-Aufruf (Request)
    await context.Response.WriteAsync("Hallo ");
    
    // Ruft die nächste Middleware auf
    await next(context); 
    
    // Logik NACH dem nächsten Middleware-Aufruf (Response)
    // Hier können wir die Antwort noch bearbeiten, nachdem der Rest der Pipeline fertig ist.
});

Die Reihenfolge der Middleware (The Middleware Order)

Die Reihenfolge, in der Middleware in Program.cs registriert wird, ist entscheidend. Die Pipeline wird in der Reihenfolge der Registrierung durchlaufen (für den Request) und in umgekehrter Reihenfolge wieder zurück (für die Response).

Empfohlene Reihenfolge

  1. Exception Handler (UseDeveloperExceptionPage, UseExceptionHandler): Sollte ganz oben stehen, um Fehler aus jedem Teil der Pipeline abzufangen.
  2. HSTS & HTTPS Redirection (UseHsts, UseHttpsRedirection): Sicherheit geht vor.
  3. Static Files (UseStaticFiles): Statische Dateien sollten schnell ausgeliefert werden, ohne unnötige Verarbeitung durch spätere Logik.
  4. Routing (UseRouting): Ermittelt, welcher Endpunkt passt.
  5. CORS (UseCors): Cross-Origin Resource Sharing.
  6. Authentication (UseAuthentication): Wer ist der Benutzer?
  7. Authorization (UseAuthorization): Darf der Benutzer das?
  8. Benutzerdefinierte Middleware: Ihre eigene Logik.
  9. Endpunkte (MapControllers, UseEndpoints, app.Run): Die eigentliche Verarbeitung der Anfrage.

Custom Middleware erstellen

Es gibt zwei Hauptwege, eigene Middleware zu schreiben: als Klasse mit IMiddleware (Factory-based) oder als konventionelle Klasse.

1. Middleware mit IMiddleware (Factory-based)

Diese Methode ist stark typisiert und nutzt Dependency Injection voll aus. Die Klasse muss im DI-Container registriert werden (z.B. als Transient).

using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

public class MyFactoryMiddleware : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        await context.Response.WriteAsync("Factory Middleware Start\n");
        await next(context);
        await context.Response.WriteAsync("Factory Middleware Ende\n");
    }
}

Registrierung:

// In Program.cs
builder.Services.AddTransient<MyFactoryMiddleware>();
// ...
app.UseMiddleware<MyFactoryMiddleware>();

2. Konventionelle Middleware

Dies ist der häufigste Weg. Die Klasse benötigt kein Interface, muss aber einer bestimmten Struktur folgen:

  • Einen öffentlichen Konstruktor, der RequestDelegate als Parameter nimmt.
  • Eine Methode Invoke oder InvokeAsync, die HttpContext nimmt und einen Task zurückgibt.
public class HelloCustomMiddleware
{
    private readonly RequestDelegate _next;

    public HelloCustomMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        // Beispiel: Prüfen auf Query-Parameter
        if (httpContext.Request.Query.ContainsKey("firstname") && 
            httpContext.Request.Query.ContainsKey("lastname"))
        {
            string fullName = $"{httpContext.Request.Query[\"firstname\"]} {httpContext.Request.Query[\"lastname\"]}";
            await httpContext.Response.WriteAsync($"Hallo {fullName}\n");
        }

        // WICHTIG: Nächste Middleware aufrufen
        await _next(httpContext); 
    }
}

Extension Method für saubere Registrierung: Es ist "Best Practice", eine Extension-Methode für IApplicationBuilder zu erstellen.

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseHelloCustomMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<HelloCustomMiddleware>();
    }
}

// Verwendung in Program.cs
app.UseHelloCustomMiddleware();

Bedingte Ausführung mit UseWhen

Mit UseWhen können Sie eine Verzweigung in der Pipeline erstellen, die nur unter bestimmten Bedingungen ausgeführt wird. Die Haupt-Pipeline wird danach wieder zusammengeführt (im Gegensatz zu Map, das oft eine Sackgasse ist).

Syntax:

app.UseWhen(
    context => context.Request.Query.ContainsKey("username"), // Bedingung (Predicate)
    appBuilder => 
    {
        // Diese Middleware läuft nur, wenn die Bedingung wahr ist
        appBuilder.Use(async (context, next) =>
        {
            await context.Response.WriteAsync("Hallo vom Branch!\n");
            await next();
        });
    }
);

Szenarien für UseWhen:

  • Logging nur für bestimmte Pfade oder User.
  • Spezielle Header nur für API-Requests setzen.
  • Bedingte Diagnosetools.

Zusammenfassung

  • Middleware bildet das Rückgrat einer ASP.NET Core Anwendung.
  • Reihenfolge ist wichtig: Von globalen Anliegen (Error Handling) zu spezifischen (Routing, Auth) zu Endpunkten.
  • app.Use kettet Komponenten aneinander, app.Run beendet die Kette.
  • Custom Middleware kann einfach als Klasse implementiert werden, um wiederverwendbare Logik zu kapseln.

Weblinks


Kategorien: Keine
Zuletzt aktualisiert am 15.02.2026 23:58